home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Open Source / AutoHotKey / Source / AutoHotkey104705_source.exe / source / util.h < prev    next >
Encoding:
C/C++ Source or Header  |  2007-06-18  |  27.7 KB  |  577 lines

  1. /*
  2. AutoHotkey
  3.  
  4. Copyright 2003-2007 Chris Mallett (support@autohotkey.com)
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15. */
  16.  
  17. #ifndef util_h
  18. #define util_h
  19.  
  20. #include "stdafx.h" // pre-compiled headers
  21. #include "defines.h"
  22. EXTERN_G;  // For ITOA() and related functions' use of g.FormatIntAsHex
  23.  
  24. #define IS_SPACE_OR_TAB(c) (c == ' ' || c == '\t')
  25. #define IS_SPACE_OR_TAB_OR_NBSP(c) (c == ' ' || c == '\t' || c == -96) // Use a negative to support signed chars.
  26.  
  27. // v1.0.43.04: The following are macros to avoid crash bugs caused by improper casting, namely a failure to cast
  28. // a signed char to UCHAR before promoting it to LPSTR, which crashes since CharLower/Upper would interpret
  29. // such a high unsigned value as an address rather than a single char.
  30. #define ltolower(ch) CharLower((LPSTR)(UCHAR)(ch))  // "L" prefix stands for "locale", like lstrcpy.
  31. #define ltoupper(ch) CharUpper((LPSTR)(UCHAR)(ch))  // For performance, some callers don't want return value cast to char.
  32.  
  33. // NOTE: MOVING THINGS OUT OF THIS FILE AND INTO util.cpp can hurt benchmarks by 10% or more, so be careful
  34. // when doing so (even when the change seems inconsequential, it can impact benchmarks due to quirks of code
  35. // generation and caching).
  36.  
  37.  
  38. inline char *StrToTitleCase(char *aStr)
  39. // Inline functions like the following probably don't actually get put inline by the compiler (since it knows
  40. // it's not worth it).  However, changing this to be non-inline has a significant impact on benchmarks even
  41. // though the function is never called by those benchmarks, probably due to coincidences in how the generated
  42. // code gets cached in the CPU.  So it seems best not to mess with anything without making sure it doesn't
  43. // drop the benchmarks significantly.
  44. {
  45.     if (!aStr) return aStr;
  46.     char *aStr_orig = aStr;    
  47.     for (bool convert_next_alpha_char_to_upper = true; *aStr; ++aStr)
  48.     {
  49.         if (IsCharAlpha(*aStr)) // Use this to better support chars from non-English languages.
  50.         {
  51.             if (convert_next_alpha_char_to_upper)
  52.             {
  53.                 *aStr = (char)ltoupper(*aStr);
  54.                 convert_next_alpha_char_to_upper = false;
  55.             }
  56.             else
  57.                 *aStr = (char)ltolower(*aStr);
  58.         }
  59.         else
  60.             if (isspace((UCHAR)*aStr))
  61.                 convert_next_alpha_char_to_upper = true;
  62.         // Otherwise, it's a digit, punctuation mark, etc. so nothing needs to be done.
  63.     }
  64.     return aStr_orig;
  65. }
  66.  
  67.  
  68.  
  69. inline char *StrChrAny(char *aStr, char *aCharList)
  70. // Returns the position of the first char in aStr that is of any one of the characters listed in aCharList.
  71. // Returns NULL if not found.
  72. // Update: Yes, this seems identical to strpbrk().  However, since the corresponding code would
  73. // have to be added to the EXE regardless of which was used, there doesn't seem to be much
  74. // advantage to switching (especially since if the two differ in behavior at all, things might
  75. // get broken).  Another reason is the name "strpbrk()" is not as easy to remember.
  76. {
  77.     if (aStr == NULL || aCharList == NULL) return NULL;
  78.     if (!*aStr || !*aCharList) return NULL;
  79.     // Don't use strchr() because that would just find the first occurrence
  80.     // of the first search-char, which is not necessarily the first occurrence
  81.     // of *any* search-char:
  82.     char *look_for_this_char, char_being_analyzed;
  83.     for (; *aStr; ++aStr)
  84.         // If *aStr is any of the search char's, we're done:
  85.         for (char_being_analyzed = *aStr, look_for_this_char = aCharList; *look_for_this_char; ++look_for_this_char)
  86.             if (char_being_analyzed == *look_for_this_char)
  87.                 return aStr;  // Match found.
  88.     return NULL; // No match.
  89. }
  90.  
  91.  
  92.  
  93. inline char *omit_leading_whitespace(char *aBuf) // 10/17/2006: __forceinline didn't help significantly.
  94. // While aBuf points to a whitespace, moves to the right and returns the first non-whitespace
  95. // encountered.
  96. {
  97.     for (; IS_SPACE_OR_TAB(*aBuf); ++aBuf);
  98.     return aBuf;
  99. }
  100.  
  101.  
  102.  
  103. inline char *omit_leading_any(char *aBuf, char *aOmitList, size_t aLength)
  104. // Returns the address of the first character in aBuf that isn't a member of aOmitList.
  105. // But no more than aLength characters of aBuf will be considered.  If aBuf is composed
  106. // entirely of omitted characters, the address of the char after the last char in the
  107. // string will returned (that char will be the zero terminator unless aLength explicitly
  108. // caused only part of aBuf to be considered).
  109. {
  110.     char *cp;
  111.     for (size_t i = 0; i < aLength; ++i, ++aBuf)
  112.     {
  113.         // Check if the current char is a member of the omitted-char list:
  114.         for (cp = aOmitList; *cp; ++cp)
  115.             if (*aBuf == *cp) // Match found.
  116.                 break;
  117.         if (!*cp) // No match found, so this character is not omitted, thus we immediately return it's position.
  118.             return aBuf;
  119.     }
  120.     // Since the above didn't return, aBuf is the position of the zero terminator or (if aLength
  121.     // indicated only a substring) the position of the char after the last char in the substring.
  122.     return aBuf;
  123. }
  124.  
  125.  
  126.  
  127. inline char *omit_trailing_whitespace(char *aBuf, char *aBuf_marker)
  128. // aBuf_marker must be a position in aBuf (to the right of it).
  129. // Starts at aBuf_marker and keeps moving to the left until a non-whitespace
  130. // char is encountered.  Returns the position of that char.
  131. {
  132.     for (; aBuf_marker > aBuf && IS_SPACE_OR_TAB(*aBuf_marker); --aBuf_marker);
  133.     return aBuf_marker;  // Can equal aBuf.
  134. }
  135.  
  136.  
  137.  
  138. inline size_t omit_trailing_any(char *aBuf, char *aOmitList, char *aBuf_marker)
  139. // aBuf_marker must be a position in aBuf (to the right of it).
  140. // Starts at aBuf_marker and keeps moving to the left until a char that isn't a member
  141. // of aOmitList is found.  The length of the remaining substring is returned.
  142. // That length will be zero if the string consists entirely of omitted characters.
  143. {
  144.     char *cp;
  145.     for (; aBuf_marker > aBuf; --aBuf_marker)
  146.     {
  147.         // Check if the current char is a member of the omitted-char list:
  148.         for (cp = aOmitList; *cp; ++cp)
  149.             if (*aBuf_marker == *cp) // Match found.
  150.                 break;
  151.         if (!*cp) // No match found, so this character is not omitted, thus we immediately return.
  152.             return (aBuf_marker - aBuf) + 1; // The length of the string when trailing chars are omitted.
  153.     }
  154.     // Since the above didn't return, aBuf_marker is now equal to aBuf.  If this final character is itself
  155.     // a member of the omitted-list, the length returned will be zero.  Otherwise it will be 1:
  156.     for (cp = aOmitList; *cp; ++cp)
  157.         if (*aBuf_marker == *cp) // Match found.
  158.             return 0;
  159.     return 1;
  160. }
  161.  
  162.  
  163.  
  164. inline size_t ltrim(char *aStr, size_t aLength = -1)
  165. // Caller must ensure that aStr is not NULL.
  166. // v1.0.25: Returns the length if it was discovered as a result of the operation, or aLength otherwise.
  167. // This greatly improves the performance of PerformAssign().
  168. // NOTE: THIS VERSION trims only tabs and spaces.  It specifically avoids
  169. // trimming newlines because some callers want to retain those.
  170. {
  171.     if (!*aStr) return 0;
  172.     char *ptr;
  173.     // Find the first non-whitespace char (which might be the terminator):
  174.     for (ptr = aStr; IS_SPACE_OR_TAB(*ptr); ++ptr); // Self-contained loop.
  175.     // v1.0.25: If no trimming needed, don't do the memmove.  This seems to make a big difference
  176.     // in the performance of critical sections of the program such as PerformAssign():
  177.     size_t offset;
  178.     if (offset = ptr - aStr) // Assign.
  179.     {
  180.         if (aLength == -1)
  181.             aLength = strlen(ptr); // Set aLength as new/trimmed length, for use below and also as the return value.
  182.         else // v1.0.25.05 bug-fix: Must adjust the length provided by caller to reflect what we did here.
  183.             aLength -= offset;
  184.         memmove(aStr, ptr, aLength + 1); // +1 to include the '\0'.  memmove() permits source & dest to overlap.
  185.     }
  186.     return aLength; // This will return -1 if the block above didn't execute and caller didn't specify the length.
  187. }
  188.  
  189. inline size_t rtrim(char *aStr, size_t aLength = -1)
  190. // Caller must ensure that aStr is not NULL.
  191. // To improve performance, caller may specify a length (e.g. when it is already known).
  192. // v1.0.25: Always returns the new length of the string.  This greatly improves the performance of
  193. // PerformAssign().
  194. // NOTE: THIS VERSION trims only tabs and spaces.  It specifically avoids trimming newlines because
  195. // some callers want to retain those.
  196. {
  197.     if (!*aStr) return 0; // The below relies upon this check having been done.
  198.     // It's done this way in case aStr just happens to be address 0x00 (probably not possible
  199.     // on Intel & Intel-clone hardware) because otherwise --cp would decrement, causing an
  200.     // underflow since pointers are probably considered unsigned values, which would
  201.     // probably cause an infinite loop.  Extremely unlikely, but might as well try
  202.     // to be thorough:
  203.     if (aLength == -1)
  204.         aLength = strlen(aStr); // Set aLength for use below and also as the return value.
  205.     for (char *cp = aStr + aLength - 1; ; --cp, --aLength)
  206.     {
  207.         if (!IS_SPACE_OR_TAB(*cp))
  208.         {
  209.             cp[1] = '\0';
  210.             return aLength;
  211.         }
  212.         // Otherwise, it is a space or tab...
  213.         if (cp == aStr) // ... and we're now at the first character of the string...
  214.         {
  215.             if (IS_SPACE_OR_TAB(*cp)) // ... and that first character is also a space or tab...
  216.             {
  217.                 *cp = '\0'; // ... so the entire string is made empty...
  218.                 return 0; // Fix for v1.0.39: Must return 0 not aLength in this case.
  219.             }
  220.             return aLength; // ... and we return in any case.
  221.         }
  222.         // else it's a space or tab, and there are still more characters to check.  Let the loop
  223.         // do its decrements.
  224.     }
  225. }
  226.  
  227. inline size_t rtrim_with_nbsp(char *aStr, size_t aLength = -1)
  228. // Returns the new length of the string.
  229. // Caller must ensure that aStr is not NULL.
  230. // To improve performance, caller may specify a length (e.g. when it is already known).
  231. // Same as rtrim but also gets rid of those annoying nbsp (non breaking space) chars that sometimes
  232. // wind up on the clipboard when copied from an HTML document, and thus get pasted into the text
  233. // editor as part of the code (such as the sample code in some of the examples).
  234. {
  235.     if (!*aStr) return 0; // The below relies upon this check having been done.
  236.     if (aLength == -1)
  237.         aLength = strlen(aStr); // Set aLength for use below and also as the return value.
  238.     for (char *cp = aStr + aLength - 1; ; --cp, --aLength)
  239.     {
  240.         if (!IS_SPACE_OR_TAB_OR_NBSP(*cp))
  241.         {
  242.             cp[1] = '\0';
  243.             return aLength;
  244.         }
  245.         if (cp == aStr)
  246.         {
  247.             if (IS_SPACE_OR_TAB_OR_NBSP(*cp)) // ... and that first character is also a space or tab...
  248.             {
  249.                 *cp = '\0'; // ... so the entire string is made empty...
  250.                 return 0; // Fix for v1.0.39: Must return 0 not aLength in this case.
  251.             }
  252.             return aLength; // ... and we return in any case.
  253.         }
  254.     }
  255. }
  256.  
  257. inline size_t trim(char *aStr, size_t aLength = -1)
  258. // Caller must ensure that aStr is not NULL.
  259. // Returns new length of aStr.
  260. // To improve performance, caller may specify a length (e.g. when it is already known).
  261. // NOTE: THIS VERSION trims only tabs and spaces.  It specifically avoids
  262. // trimming newlines because some callers want to retain those.
  263. {
  264.     aLength = ltrim(aStr, aLength);  // It may return -1 to indicate that it still doesn't know the length.
  265.     return rtrim(aStr, aLength);
  266.     // v1.0.25: rtrim() always returns the new length of the string.  This greatly improves the
  267.     // performance of PerformAssign() and possibly other things.
  268. }
  269.  
  270. inline size_t strip_trailing_backslash(char *aPath)
  271. // Removes any backslash (if there is one).
  272. // Returns length of the new string to allow some callers to avoid another strlen() call.
  273. {
  274.     size_t length = strlen(aPath);
  275.     if (!length) // Below relies on this check having been done to prevent underflow.
  276.         return length;
  277.     char *cp = aPath + length - 1;
  278.     if (*cp == '\\')
  279.     {
  280.         *cp = '\0';
  281.         return length - 1;
  282.     }
  283.     // Otherwise there no slash to remove, so return the current length.
  284.     return length;
  285. }
  286.  
  287.  
  288. // Transformation is the same in either direction because the end bytes are swapped
  289. // and the middle byte is left as-is:
  290. #define bgr_to_rgb(aBGR) rgb_to_bgr(aBGR)
  291. inline COLORREF rgb_to_bgr(DWORD aRGB)
  292. // Fancier methods seem prone to problems due to byte alignment or compiler issues.
  293. {
  294.     return RGB(GetBValue(aRGB), GetGValue(aRGB), GetRValue(aRGB));
  295. }
  296.  
  297.  
  298.  
  299. inline bool IsHex(char *aBuf) // 10/17/2006: __forceinline worsens performance, but physically ordering it near ATOI64() [via /ORDER] boosts by 3.5%.
  300. // Note: AHK support for hex ints reduces performance by only 10% for decimal ints, even in the tightest
  301. // of math loops that have SetBatchLines set to -1.
  302. {
  303.     // For whatever reason, omit_leading_whitespace() benches consistently faster (albeit slightly) than
  304.     // the same code put inline (confirmed again on 10/17/2006, though the difference is hardly anything):
  305.     //for (; IS_SPACE_OR_TAB(*aBuf); ++aBuf);
  306.     aBuf = omit_leading_whitespace(aBuf); // i.e. caller doesn't have to have ltrimmed.
  307.     if (!*aBuf)
  308.         return false;
  309.     if (*aBuf == '-' || *aBuf == '+')
  310.         ++aBuf;
  311.     // The "0x" prefix must be followed by at least one hex digit, otherwise it's not considered hex:
  312.     #define IS_HEX(buf) (*buf == '0' && (*(buf + 1) == 'x' || *(buf + 1) == 'X') && isxdigit(*(buf + 2)))
  313.     return IS_HEX(aBuf);
  314. }
  315.  
  316.  
  317.  
  318. // As of v1.0.30, ATOI(), ITOA() and the other related functions below are no longer macros
  319. // because there are too many places where something like ATOI(++cp) is done, which would be a
  320. // bug if not caught since cp would be incremented more than once if the macro referred to that
  321. // arg more than once.  In addition, a non-comprehensive, simple benchmark shows that the
  322. // macros don't perform any better anyway, probably in part because there are many times when
  323. // something like ATOI(ARG1) is called, which forces the ARG1 macro to be expanded two or more
  324. // times within ATOI (when it was a macro).  So for now, the below are declared as inline.
  325. // However, it seems that the compiler chooses not to make them truly inline, which as it
  326. // turns out is probably the right decision since a simple benchmark shows that even with
  327. // __forceinline in effect for all of them (which is confirmed to actually force inline),
  328. // the performance isn't any better.
  329.  
  330. inline __int64 ATOI64(char *buf)
  331. // The following comment only applies if the code is a macro or actually put inline by the compiler,
  332. // which is no longer true:
  333. // A more complex macro is used for ATOI64(), since it is more often called from places where
  334. // performance matters (e.g. ACT_ADD).  It adds about 500 bytes to the code size  in exchance for
  335. // a 8% faster math loops.  But it's probably about 8% slower when used with hex integers, but
  336. // those are so rare that the speed-up seems worth the extra code size:
  337. //#define ATOI64(buf) _strtoi64(buf, NULL, 0) // formerly used _atoi64()
  338. {
  339.     return IsHex(buf) ? _strtoi64(buf, NULL, 16) : _atoi64(buf);  // _atoi64() has superior performance, so use it when possible.
  340. }
  341.  
  342. inline unsigned __int64 ATOU64(char *buf)
  343. {
  344.     return _strtoui64(buf, NULL, IsHex(buf) ? 16 : 10);
  345. }
  346.  
  347. inline int ATOI(char *buf)
  348. {
  349.     // Below has been updated because values with leading zeros were being intepreted as
  350.     // octal, which is undesirable.
  351.     // Formerly: #define ATOI(buf) strtol(buf, NULL, 0) // Use zero as last param to support both hex & dec.
  352.     return IsHex(buf) ? strtol(buf, NULL, 16) : atoi(buf); // atoi() has superior performance, so use it when possible.
  353. }
  354.  
  355. // v1.0.38.01: Make ATOU a macro that refers to ATOI64() to improve performance (takes advantage of _atoi64()
  356. // being considerably faster than strtoul(), at least when the number is non-hex).  This relies on the fact
  357. // that ATOU() and (UINT)ATOI64() produce the same result due to the way casting works.  For example:
  358. // ATOU("-1") == (UINT)ATOI64("-1")
  359. // ATOU("-0xFFFFFFFF") == (UINT)ATOI64("-0xFFFFFFFF")
  360. #define ATOU(buf) (UINT)ATOI64(buf)
  361. //inline unsigned long ATOU(char *buf)
  362. //{
  363. //    // As a reminder, strtoul() also handles negative numbers.  For example, ATOU("-1") is
  364. //    // 4294967295 (0xFFFFFFFF) and ATOU("-2") is 4294967294.
  365. //    return strtoul(buf, NULL, IsHex(buf) ? 16 : 10);
  366. //}
  367.  
  368. inline double ATOF(char *buf)
  369. // Unlike some Unix versions of strtod(), the VC++ version does not seem to handle hex strings
  370. // such as "0xFF" automatically.  So this macro must check for hex because some callers rely on that.
  371. // Also, it uses _strtoi64() vs. strtol() so that more of a double's capacity can be utilized:
  372. {
  373.     return IsHex(buf) ? (double)_strtoi64(buf, NULL, 16) : atof(buf);
  374. }
  375.  
  376. inline char *ITOA(int value, char *buf)
  377. {
  378.     if (g.FormatIntAsHex)
  379.     {
  380.         char *our_buf_temp = buf;
  381.         // Negative hex numbers need special handling, otherwise something like zero minus one would create
  382.         // a huge 0xffffffffffffffff value, which would subsequently not be read back in correctly as
  383.         // a negative number (but UTOA() doesn't need this since there can't be negatives in that case).
  384.         if (value < 0)
  385.             *our_buf_temp++ = '-';
  386.         *our_buf_temp++ = '0';
  387.         *our_buf_temp++ = 'x';
  388.         _itoa(value < 0 ? -(int)value : value, our_buf_temp, 16);
  389.         // Must not return the result of the above because it's our_buf_temp and we want buf.
  390.         return buf;
  391.     }
  392.     else
  393.         return _itoa(value, buf, 10);
  394. }
  395.  
  396. inline char *ITOA64(__int64 value, char *buf)
  397. {
  398.     if (g.FormatIntAsHex)
  399.     {
  400.         char *our_buf_temp = buf;
  401.         if (value < 0)
  402.             *our_buf_temp++ = '-';
  403.         *our_buf_temp++ = '0';
  404.         *our_buf_temp++ = 'x';
  405.         _i64toa(value < 0 ? -(__int64)value : value, our_buf_temp, 16);
  406.         // Must not return the result of the above because it's our_buf_temp and we want buf.
  407.         return buf;
  408.     }
  409.     else
  410.         return _i64toa(value, buf, 10);
  411. }
  412.  
  413. inline char *UTOA(unsigned long value, char *buf)
  414. {
  415.     if (g.FormatIntAsHex)
  416.     {
  417.         *buf = '0';
  418.         *(buf + 1) = 'x';
  419.         _ultoa(value, buf + 2, 16);
  420.         // Must not return the result of the above because it's buf + 2 and we want buf.
  421.         return buf;
  422.     }
  423.     else
  424.         return _ultoa(value, buf, 10);
  425. }
  426.  
  427. // Not currently used:
  428. //inline char *UTOA64(unsigned __int64 value, char *buf) 
  429. //{
  430. //    if (g.FormatIntAsHex)
  431. //    {
  432. //        *buf = '0';
  433. //        *(buf + 1) = 'x';
  434. //        return _ui64toa(value, buf + 2, 16);
  435. //    }
  436. //    else
  437. //        return _ui64toa(value, buf, 10);
  438. //}
  439.  
  440.  
  441.  
  442. //inline char *strcatmove(char *aDst, char *aSrc)
  443. //// Same as strcat() but allows aSrc and aDst to overlap.
  444. //// Unlike strcat(), it doesn't return aDst.  Instead, it returns the position
  445. //// in aDst where aSrc was appended.
  446. //{
  447. //    if (!aDst || !aSrc || !*aSrc) return aDst;
  448. //    char *aDst_end = aDst + strlen(aDst);
  449. //    return (char *)memmove(aDst_end, aSrc, strlen(aSrc) + 1);  // Add 1 to include aSrc's terminator.
  450. //}
  451.  
  452.  
  453.  
  454. // v1.0.43.03: The following macros support the new "StringCaseSense Locale" setting.  This setting performs
  455. // 1 to 10 times slower for most things, but has the benefit of seeing characters like Σ and ─ as identical
  456. // when insensitive.  MSDN implies that lstrcmpi() is the same as:
  457. //     CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, ...)
  458. // Note that when MSDN talks about the "word sort" vs. "string sort", it does not mean that strings like
  459. // "co-op" and "co-op" are considered equal.  Instead, they are considered closer together than the traditional
  460. // string sort would see them, so that they wind up together in a sorted list.
  461. // And both of them benchmark the same, so lstrcmpi is now used here and in various other places throughout
  462. // the program when the new locale-case-insensitive mode is in effect.
  463. #define strcmp2(str1, str2, string_case_sense) ((string_case_sense) == SCS_INSENSITIVE ? stricmp(str1, str2) \
  464.     : ((string_case_sense) == SCS_INSENSITIVE_LOCALE ? lstrcmpi(str1, str2) : strcmp(str1, str2)))
  465. #define g_strcmp(str1, str2) strcmp2(str1, str2, g.StringCaseSense)
  466. // The most common mode is listed first for performance:
  467. #define strstr2(haystack, needle, string_case_sense) ((string_case_sense) == SCS_INSENSITIVE ? strcasestr(haystack, needle) \
  468.     : ((string_case_sense) == SCS_INSENSITIVE_LOCALE ? lstrcasestr(haystack, needle) : strstr(haystack, needle)))
  469. #define g_strstr(haystack, needle) strstr2(haystack, needle, g.StringCaseSense)
  470. // For the following, caller must ensure that len1 and len2 aren't beyond the terminated length of the string
  471. // because CompareString() might not stop at the terminator when a length is specified.  Also, CompareString()
  472. // returns 0 on failure, but failure occurs only when parameter/flag is invalid, which should never happen in
  473. // this case.
  474. #define lstrcmpni(str1, len1, str2, len2) (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, str1, (int)(len1), str2, (int)(len2)) - 2) // -2 for maintainability
  475.  
  476. // The following macros simplify and make consistent the calls to MultiByteToWideChar().
  477. // MSDN implies that passing -1 for cbMultiByte is the most typical and secure usage because it ensures
  478. // that the output is null-terminated: "the resulting wide character string has a null terminator, and the
  479. // length returned by the function includes the terminating null character."
  480. //
  481. // I couldn't find any info on when MB_PRECOMPOSED is needed (if ever).  It's the default anyway,
  482. // which implies that passing zero (which is quite common in many examples I've seen) is essentially
  483. // the same as passing MB_PRECOMPOSED.  However, some modes such as CP_UTF8 should never use MB_PRECOMPOSED
  484. // or the function will fail.
  485. //
  486. // #1: FROM ANSI TO UNICODE (UTF-16).  dest_size_in_wchars includes the terminator.
  487. // From looking at the source to mbstowcs(), it might be faster when the "C" locale is in effect (which is
  488. // the default in the absence of setlocale()) than MultiByteToWideChar() depending on how the latter is
  489. // implemented. This is because mbstowcs() simply casts the characters to (wchar_t)(unsigned char) without
  490. // any other translation at all.  Although that behavior is probably identical to MultiByteToWideChar(CP_ACP...),
  491. // it's not completely certain -- so it seems best to stick with MultiByteToWideChar() for consistency
  492. // (also, avoiding mbstowcs slightly reduces code size).  If there's ever a case where performance is
  493. // important, create a simple casting loop (see mbstowcs.c for an example) that converts source to dest,
  494. // and test if it performs significantly better than MultiByteToWideChar(CP_ACP...).
  495. #define ToWideChar(source, dest, dest_size_in_wchars) MultiByteToWideChar(CP_ACP, 0, source, -1, dest, dest_size_in_wchars)
  496. //
  497. // #2: FROM UTF-8 TO UNICODE (UTF-16). dest_size_in_wchars includes the terminator.  MSDN: "For UTF-8, dwFlags must be set to either 0 or MB_ERR_INVALID_CHARS. Otherwise, the function fails with ERROR_INVALID_FLAGS."
  498. #define UTF8ToWideChar(source, dest, dest_size_in_wchars) MultiByteToWideChar(CP_UTF8, 0, source, -1, dest, dest_size_in_wchars)
  499. //
  500. // #3: FROM UNICODE (UTF-16) TO UTF-8. dest_size_in_bytes includes the terminator.
  501. #define WideCharToUTF8(source, dest, dest_size_in_bytes) WideCharToMultiByte(CP_UTF8, 0, source, -1, dest, dest_size_in_bytes, NULL, NULL)
  502.  
  503. // v1.0.44.03: Callers now use the following macro rather than the old approach.  However, this change
  504. // is meaningful only to people who use more than one keyboard layout.  In the case of hotstrings:
  505. // It seems that the vast majority of them would want the Hotstring monitoring to adhere to the active
  506. // window's current keyboard layout rather than the script's.  This change is somewhat less certain to
  507. // be desirable uncondionally for the Input command (especially invisible/non-V-option Inputs); but it 
  508. // seems best to use the same approach to avoid calling ToAsciiEx() more than once in cases where a
  509. // script has hotstrings and also uses the Input command. Calling ToAsciiEx() twice in such a case would
  510. // be likely to aggravate its side effects with dead keys as described at length in the hook/Input code).
  511. #define Get_active_window_keybd_layout \
  512.     HWND active_window;\
  513.     HKL active_window_keybd_layout = GetKeyboardLayout((active_window = GetForegroundWindow())\
  514.         ? GetWindowThreadProcessId(active_window, NULL) : 0); // When no foreground window, the script's own layout seems like the safest default.
  515.  
  516. #define DATE_FORMAT_LENGTH 14 // "YYYYMMDDHHMISS"
  517. #define IS_LEAP_YEAR(year) ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  518.  
  519. int GetYDay(int aMon, int aDay, bool aIsLeapYear);
  520. int GetISOWeekNumber(char *aBuf, int aYear, int aYDay, int aWDay);
  521. ResultType YYYYMMDDToFileTime(char *aYYYYMMDD, FILETIME &aFileTime);
  522. DWORD YYYYMMDDToSystemTime2(char *aYYYYMMDD, SYSTEMTIME *aSystemTime);
  523. ResultType YYYYMMDDToSystemTime(char *aYYYYMMDD, SYSTEMTIME &aSystemTime, bool aDoValidate);
  524. char *FileTimeToYYYYMMDD(char *aBuf, FILETIME &aTime, bool aConvertToLocalTime = false);
  525. char *SystemTimeToYYYYMMDD(char *aBuf, SYSTEMTIME &aTime);
  526. __int64 YYYYMMDDSecondsUntil(char *aYYYYMMDDStart, char *aYYYYMMDDEnd, bool &aFailed);
  527. __int64 FileTimeSecondsUntil(FILETIME *pftStart, FILETIME *pftEnd);
  528.  
  529. SymbolType IsPureNumeric(char *aBuf, BOOL aAllowNegative = false // BOOL vs. bool might squeeze a little more performance out of this frequently-called function.
  530.     , BOOL aAllowAllWhitespace = true, BOOL aAllowFloat = false, BOOL aAllowImpure = false);
  531.  
  532. void strlcpy(char *aDst, const char *aSrc, size_t aDstSize);
  533. int snprintf(char *aBuf, int aBufSize, const char *aFormat, ...);
  534. int snprintfcat(char *aBuf, int aBufSize, const char *aFormat, ...);
  535. // Not currently used by anything, so commented out to possibly reduce code size:
  536. //int strlcmp (char *aBuf1, char *aBuf2, UINT aLength1 = UINT_MAX, UINT aLength2 = UINT_MAX);
  537. int strlicmp(char *aBuf1, char *aBuf2, UINT aLength1 = UINT_MAX, UINT aLength2 = UINT_MAX);
  538. char *strrstr(char *aStr, char *aPattern, StringCaseSenseType aStringCaseSense, int aOccurrence = 1);
  539. char *lstrcasestr(const char *phaystack, const char *pneedle);
  540. char *strcasestr (const char *phaystack, const char *pneedle);
  541. UINT StrReplace(char *aHaystack, char *aOld, char *aNew, StringCaseSenseType aStringCaseSense
  542.     , UINT aLimit = UINT_MAX, size_t aSizeLimit = -1, char **aDest = NULL, size_t *aHaystackLength = NULL);
  543. int PredictReplacementSize(int aLengthDelta, int aReplacementCount, int aLimit, int aHaystackLength
  544.     , int aCurrentLength, int aEndOffsetOfCurrMatch);
  545. char *TranslateLFtoCRLF(char *aString);
  546. bool DoesFilePatternExist(char *aFilePattern, DWORD *aFileAttr = NULL);
  547. #ifdef _DEBUG
  548.     ResultType FileAppend(char *aFilespec, char *aLine, bool aAppendNewline = true);
  549. #endif
  550. char *ConvertFilespecToCorrectCase(char *aFullFileSpec);
  551. char *FileAttribToStr(char *aBuf, DWORD aAttr);
  552. unsigned __int64 GetFileSize64(HANDLE aFileHandle);
  553. char *GetLastErrorText(char *aBuf, int aBufSize, bool aUpdateLastError = false);
  554. void AssignColor(char *aColorName, COLORREF &aColor, HBRUSH &aBrush);
  555. COLORREF ColorNameToBGR(char *aColorName);
  556. HRESULT MySetWindowTheme(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
  557. //HRESULT MyEnableThemeDialogTexture(HWND hwnd, DWORD dwFlags);
  558. char *ConvertEscapeSequences(char *aBuf, char aEscapeChar, bool aAllowEscapedSpace);
  559. POINT CenterWindow(int aWidth, int aHeight);
  560. bool FontExist(HDC aHdc, char *aTypeface);
  561. void ScreenToWindow(POINT &aPoint, HWND aHwnd);
  562. void WindowToScreen(int &aX, int &aY);
  563. void GetVirtualDesktopRect(RECT &aRect);
  564. LPVOID AllocInterProcMem(HANDLE &aHandle, DWORD aSize, HWND aHwnd);
  565. void FreeInterProcMem(HANDLE aHandle, LPVOID aMem);
  566.  
  567. DWORD GetEnvVarReliable(char *aEnvVarName, char *aBuf);
  568. DWORD ReadRegString(HKEY aRootKey, char *aSubkey, char *aValueName, char *aBuf, size_t aBufSize);
  569.  
  570. HBITMAP LoadPicture(char *aFilespec, int aWidth, int aHeight, int &aImageType, int aIconNumber
  571.     , bool aUseGDIPlusIfAvailable);
  572. HBITMAP IconToBitmap(HICON ahIcon, bool aDestroyIcon);
  573. int CALLBACK FontEnumProc(ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, DWORD FontType, LPARAM lParam);
  574. bool IsStringInList(char *aStr, char *aList, bool aFindExactMatch);
  575.  
  576. #endif
  577.